/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.common.core.domain.model;

import org.slf4j.MDC;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;

import com.comac.ins.common.core.enums.BizEventTypeEnum;
import com.comac.ins.common.core.utils.SpringUtils;
import lombok.Data;

import static com.comac.ins.common.core.constant.Constants.TRACE_ID;

/**
 *
 * 业务事件
 * @author zhanghongyi
 * @date 2024/7/5 14:06
 * @description BizEvent
 */
@Data
public class BizEvent<T> implements ResolvableTypeProvider {
    /**
     * 业务事件载荷
     * */
    private T eventPayload;

    /**
     * 业务事件类型
     * */
    private BizEventTypeEnum eventType;

    /**
     * traceId 用于关联异步调用前后的链路
     * */
    private String traceId;

    /**
     * 是否使用异步调用，默认true
     * 当为false时，使用调用方线程执行事件，可以确保时序
     * */
    private boolean async = true;

    /**
     * 业务事件
     * @param bizEventPayload 业务事件载荷
     * @param bizEventType 业务事件类型
     * */
    public BizEvent(T bizEventPayload, BizEventTypeEnum bizEventType){
        eventPayload = bizEventPayload;
        eventType = bizEventType;
    }
    /**
     * 业务事件
     * @param bizEventPayload 业务事件载荷
     * */
    public BizEvent(T bizEventPayload){
        eventPayload = bizEventPayload;
        eventType = BizEventTypeEnum.DEFAULT_EVENT;
    }

    /**
     * 用于SpringEvent识别泛型参数
     * */
    @Override
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forClass(getEventPayload().getClass()));
    }

    /**
     * 发布事件
     * */
    public static <M> void  publishEvent(BizEvent<M> event){
        if(null == event.getTraceId()){
            event.setTraceId(MDC.get(TRACE_ID));
        }
        SpringUtils.context().publishEvent(event);
    }
    /**
     * 发布事件
     * */
    public static <M> void  publishEvent(M payload){
        BizEvent<M> event = new BizEvent<>(payload);
        event.setTraceId(MDC.get(TRACE_ID));
        SpringUtils.context().publishEvent(event);
    }
}
